package com.fingard.dsp.bank.directbank.allinpay03.util;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import java.io.IOException;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
 *  提供加密、解密、签名、验签功能
 */
public class CryptoUtil {
    /**
     * SHA1withRSA 签名
     *
     * @param source 签名源串
     * @param pkcs8_rsa_private_key  PEM编码，pkcs8形式的RSA私钥
     * @return 签名
     */
    public static String doSignBySHA1withRSA(String source, String pkcs8_rsa_private_key) throws IOException {
        PrivateKey privateKey = getRSAPrivateKey(pkcs8_rsa_private_key);
        byte[] sourceData = source.getBytes("utf-8");
        String result = null;

        try {
            Signature sign = Signature.getInstance("SHA1withRSA");
            sign.initSign(privateKey);
            sign.update(sourceData);

            byte[] resultData = sign.sign();
            result = new BASE64Encoder().encodeBuffer(resultData);

        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }

    /**
     * RSA 公钥加密
     *
     * @param plainText 明文
     * @param pkcs8_rsa_public_key PEM编码，pkcs8形式的RSA公钥
     * @return 加密后的密文
     */
    public static String doEncryptByRSA(String plainText, String pkcs8_rsa_public_key) throws IOException {
        PublicKey publicKey = getRSAPublicKey(pkcs8_rsa_public_key);
        byte[] sourceData = plainText.getBytes();
        String result = null;

        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            byte[] resultData = cipher.doFinal(sourceData);
            result = new BASE64Encoder().encodeBuffer(resultData);

        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }

    private static PublicKey getRSAPublicKey(String pkcs8_rsa_public_key) throws IOException {
        byte[] keyBytes = pkcs8_rsa_public_key.getBytes();

        String pem = new String(keyBytes);
        pem = pem.replace("-----BEGIN PUBLIC KEY-----", "");
        pem = pem.replace("-----END PUBLIC KEY-----", "");
        pem = pem.replace("\n", "");

        byte[] decoded = new BASE64Decoder().decodeBuffer(pem);
        X509EncodedKeySpec spec = new X509EncodedKeySpec(decoded);

        PublicKey publicKey = null;

        try {
            KeyFactory kf = KeyFactory.getInstance("RSA");
            publicKey = kf.generatePublic(spec);

        } catch (Exception e) {
            e.printStackTrace();
        }

        return publicKey;
    }

    private static PrivateKey getRSAPrivateKey(String pkcs8_rsa_private_key) throws IOException {
        byte[] keyBytes = pkcs8_rsa_private_key.getBytes();

        String pem = new String(keyBytes);
        pem = pem.replace("-----BEGIN PRIVATE KEY-----", "");
        pem = pem.replace("-----END PRIVATE KEY-----", "");
        pem = pem.replace("\n", "");

        byte [] decoded = new BASE64Decoder().decodeBuffer(pem);
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(decoded);

        PrivateKey privateKey = null;

        try {
            KeyFactory kf = KeyFactory.getInstance("RSA");
            privateKey = kf.generatePrivate(spec);

        } catch (Exception e) {
            e.printStackTrace();
        }

        return privateKey;
    }
}